﻿using System.Dynamic;


#pragma warning disable CS0660 // 类型定义运算符 == 或运算符 !=，但不重写 Object.Equals(object o)
#pragma warning disable CS0661 // 类型定义运算符 == 或运算符 !=，但不重写 Object.GetHashCode()
namespace zijian666.Data;

/// <summary>
/// 动态类型: 数据记录
/// </summary>
internal abstract class DynamicDictionary(object value) : DynamicAtom(value), IReadOnlyDictionary<string, object?>
{
    protected abstract bool TryGetValue(string name, out object? value);

    protected abstract DynamicAtom this[int columnIndex] { get; }

    protected abstract DynamicAtom this[string columnName] { get; }


    protected DynamicAtom this[object[] indexes]
    {
        get
        {
            if (indexes.Length != 1)
            {
                return NULL;
            }
            return indexes[0] switch
            {
                int index => this[index],
                string columnName => this[columnName],
                _ => NULL,
            };
        }
    }


    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = this[binder.Name];
        return true;
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        result = this[indexes];
        return true;
    }


    #region Equals
    public static bool operator ==(DynamicDictionary a, object b) => a?.Equals(b) ?? b == null;

    public static bool operator !=(DynamicDictionary a, object b) => !(a?.Equals(b) ?? b == null);
    #endregion



    public override string ToString()
    {
        var names = GetDynamicMemberNames();
        if (!names.Any())
        {
            return "{ }";
        }
        using (ObjectPoolHelper.GetStringBuilder(out var buffer))
        {
            buffer.Append("{ ");
            foreach (var name in names)
            {
                buffer.Append('[');
                buffer.Append(name);
                buffer.Append("] = ");
                buffer.Append(this[name]);
                buffer.Append(" ,");
            }
            buffer[buffer.Length - 1] = '}';
            return buffer.ToString();
        }
    }

    bool IReadOnlyDictionary<string, object?>.ContainsKey(string key)
        => GetDynamicMemberNames().Contains(key);

    bool IReadOnlyDictionary<string, object?>.TryGetValue(string key, out object? value)
        => TryGetValue(key, out value);

    object IReadOnlyDictionary<string, object?>.this[string key]
        => TryGetValue(key, out var value) ? value : null;

    IEnumerable<string> IReadOnlyDictionary<string, object?>.Keys
        => GetDynamicMemberNames();

    IEnumerable<object?> IReadOnlyDictionary<string, object?>.Values
    {
        get
        {
            foreach (var name in GetDynamicMemberNames())
            {
                _ = TryGetValue(name, out var value);
                yield return value;
            }
        }
    }

    int IReadOnlyCollection<KeyValuePair<string, object?>>.Count
        => GetDynamicMemberNames().Count();

    IEnumerator<KeyValuePair<string, object?>> IEnumerable<KeyValuePair<string, object?>>.GetEnumerator()
    {
        foreach (var name in GetDynamicMemberNames())
        {
            _ = TryGetValue(name, out var value);
            yield return new KeyValuePair<string, object?>(name, value);
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        foreach (var name in GetDynamicMemberNames())
        {
            _ = TryGetValue(name, out var value);
            yield return (name, value);
        }
    }
}